package zhongbo.java.air.monitor.listener;

import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.locationtech.jts.geom.Coordinate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.connection.Message;
import org.springframework.data.redis.connection.MessageListener;
import org.springframework.stereotype.Component;
import zhongbo.java.air.dictionary.mapper.AlertZoneMapper;
import zhongbo.java.air.dictionary.model.AlertZone;
import zhongbo.java.air.monitor.dto.PointDto;
import zhongbo.java.air.monitor.mapper.AirAlertLogMapper;
import zhongbo.java.air.monitor.model.AirAlertLog;
import zhongbo.java.air.monitor.model.FlightPath;
import zhongbo.java.air.monitor.service.IAirAlertLogService;
import zhongbo.java.air.monitor.service.IJtsService;
import zhongbo.java.air.monitor.util.JtsUtil;
import zhongbo.java.air.monitor.web.websocket.AlertZoneWebSocket;
import zhongbo.java.air.monitor.web.websocket.WebSocketSessionManager;

import java.sql.Timestamp;
import java.time.LocalDateTime;
import java.util.Date;
import java.util.List;

/**
 * 接收订阅频道log_chanel 发布的广播消息
 */
@Component
@Slf4j
public class RedisSubscribePathChanelListener implements MessageListener {
    @Autowired
    private AlertZoneMapper alertZoneMapper;

    @Autowired
    private AirAlertLogMapper airAlertLogMapper;

    @Autowired
    private IAirAlertLogService airAlertLogService;
    @Autowired
    private IJtsService jtsService;

    @Autowired
    private AlertZoneWebSocket alertZoneWebSocket;

    /**
     * 消息处理方法
     *
     * @param message 消息内容对象
     * @param chanel  字节数组方式的频道名称
     */
    @Override
    public void onMessage(Message message, byte[] chanel) {
        byte[] messageBody = message.getBody();
        String msgString = new String(messageBody);
        System.out.println("收到JSON数据:" + msgString);

        // 调用会话管理器进行广播
        WebSocketSessionManager.broadcast(msgString);
        FlightPath flightPath = processMessage(msgString);
        processAlert(flightPath);
    }

    private FlightPath processMessage(String msgString) {
        JSONObject jsonObject = new JSONObject(msgString);
        FlightPath flightPath = new FlightPath();

        flightPath.setIcaoCode(jsonObject.getStr("icaoCode"));
        //    flightPath.setTimestamp(jsonObject.getDate("timestamp"));---->可能导致出错：
        //    jsonObject.getDate("timestamp") 会直接将时间戳转换为 Date 对象。
        // 但这种方式可能会导致问题，因为如果时间戳值无效，Date 对象可能会生成一个不合法的日期时间值。
        // 获取时间戳
        Long timestamp = jsonObject.getLong("timestamp");
        if (timestamp != null) {
            // 检查时间戳是否在 MySQL 的支持范围内
            if (timestamp >= 1000L * 365 * 24 * 60 * 60 * 1000 && timestamp <= 9999L * 365 * 24 * 60 * 60 * 1000) {
                Date date = new Date(timestamp);
                flightPath.setTimestamp(date);
            } else {
                // 如果超出范围，设置为当前时间
                Date currentDate = new Date();
                flightPath.setTimestamp(currentDate);
            }
        } else {
            // 如果时间戳为空，设置为当前时间
            Date currentDate = new Date();
            flightPath.setTimestamp(currentDate);
        }
        flightPath.setLatitude(jsonObject.getDouble("latitude"));
        flightPath.setLongitude(jsonObject.getDouble("longitude"));
        flightPath.setAltitude(jsonObject.getDouble("altitude"));
        flightPath.setSpeed(jsonObject.getDouble("speed"));
        flightPath.setHeading(jsonObject.getDouble("heading"));
        flightPath.setSourceType(jsonObject.getStr("sourceType"));
        return flightPath;
    }

    private void processAlert(FlightPath flightPath) {
        // 查询所有警戒区
        List<AlertZone> alertZones = alertZoneMapper.selectList(null);
        if (alertZones.isEmpty()) {
            return; // 没有警戒区数据，结束告警判断
        }
        // 查询最近5分钟的告警记录
        List<AirAlertLog> alertLogs = airAlertLogMapper.selectList(null);
        for (AirAlertLog alertLog : alertLogs) {
            LocalDateTime fiveMinutesAgo = LocalDateTime.now().minusMinutes(1);
            QueryWrapper<AirAlertLog> queryWrapper = new QueryWrapper<>();
            if (alertLog != null) {
                queryWrapper.eq("icao_code", flightPath.getIcaoCode());
                queryWrapper.ge("trigger_time", Timestamp.valueOf(fiveMinutesAgo));
            }
            AirAlertLog latestAlertLog = airAlertLogMapper.selectOne(queryWrapper);
            if (latestAlertLog != null) {
                return; // 已有告警记录，结束告警判断
            }
        }
        // 遍历警戒区，判断航迹点是否在警戒区内
        for (AlertZone alertZone : alertZones) {
            List<PointDto> pointList = jtsService.parseAlertZoneVertices(alertZone.getVertices());
            boolean isInZone = jtsService.isInAlertZone(pointList, flightPath.getLongitude(), flightPath.getLatitude());
            if (isInZone) {
                // 构建告警日志记录
                AirAlertLog alertLog = new AirAlertLog();
                alertLog.setIcaoCode(flightPath.getIcaoCode());
                alertLog.setAlertZoneCode(alertZone.getZoneCode());
                alertLog.setTriggerTime(new Date());
                alertLog.setAlertZoneId(alertZone.getId());
                alertLog.setAlertType(alertZone.getZoneType());
                Coordinate coordinate = JtsUtil.createCoordinate(flightPath.getLongitude(), flightPath.getLatitude());
                // 将 Coordinate 转换为 JSON 字符串
                ObjectMapper objectMapper = new ObjectMapper();
                try {
                    String coordinateJson = objectMapper.writeValueAsString(coordinate);
                    alertLog.setTriggerCoordinates(coordinateJson);
                } catch (Exception e) {
                    // 处理异常
                    e.printStackTrace();
                }
                // 保存告警记录
                airAlertLogService.add(alertLog);
                // 广播告警信息
                //转换为json字符串
                String jsonMessage = JSONUtil.toJsonStr(alertLog);
                alertZoneWebSocket.broadcastMessage(jsonMessage);
                break; // 已触发告警，跳出循环
            }
        }
    }
}
